﻿#pragma once

#include <QImage>
#include <memory>
#include "qlib/core/object.h"
#include "qlib/core/vec2.h"
#include "qlib/geo/polygon.h"
#include "qlib/layout/property.h"
#include "qlib/layout/repetition.h"

namespace qlib {
enum struct GeoPartType;

class RectangleImg;
using RectangleImgPtrArray = std::vector<std::shared_ptr<RectangleImg>>;
using RectangleImgPtrArrayMap = std::unordered_map<Tag, RectangleImgPtrArray, Tag::Hash>;

// 0: 中心， 1: 顶点， 2: 边， 3: 边中点，4: box顶点, 5: box边, 6: box边中心
using RectangleImgParts = std::tuple<Vec2d, Vec2dArray, std::vector<Vec2dArray>, Vec2dArray, Vec2dArray, std::vector<Vec2dArray>, Vec2dArray>;

class QLIB_API RectangleImg {
 public:
  RectangleImg();
  RectangleImg(const Vec2d& _pos, double _width, double _height, uint32_t _layer = 0, uint32_t _datatype = 0);
  RectangleImg(const Vec2d& _left_bottom, const Vec2d& _right_top, uint32_t _layer = 0, uint32_t _datatype = 0);

  RectangleImg(const RectangleImg& oth);
  RectangleImg& operator=(const RectangleImg& other);

  using s_ptr = std::shared_ptr<RectangleImg>;
  template <typename... Args>
  static s_ptr create(Args... args) {
    return std::make_shared<RectangleImg>(args...);
  }
  // template <>
  static s_ptr create() {
    return std::make_shared<RectangleImg>();
  }
  static s_ptr create(const RectangleImg& value) { return std::make_shared<RectangleImg>(value); }

  double area() const;
  double perimeter();

  s_ptr copy() const;

  void init(const Vec2d& _pos, double _width, double _height, uint32_t _layer = 0, uint32_t _datatype = 0);
  void init(const Vec2d& _left_bottom, const Vec2d& _right_top, uint32_t _layer = 0, uint32_t _datatype = 0);

  Polygon::s_ptr to_polygon() const;
  Vec2dArray bounding_box() const;
  Vec2dArray bounding_box_points() { return box_to_points(bounding_box()); };

  void mirror(qlib::Vec2d p0, qlib::Vec2d p1);

  void rotate(double angle, qlib::Vec2d center);
  void translate(double dx, double dy);
  void transform(double magnification, bool x_reflection, double rotation, Vec2d origin);

  void amend();

  uint32_t getLayer();
  void setLayer(uint32_t layer);

  double getWidth();
  void setWidth(double width);

  double getHeight();
  void setHeight(double height);

  Vec2d getCenterPoint();
  void setCenterPoint(Vec2d center);

  double getRotation();
  void setRotation(double rotation);

  RectangleImgParts get_parts();
  Vec2dArray query_parts(GeoPartType type, uint32_t id);

  // 渲染
  Vec2dArray render_aabb();
  Vec2dArray render_poly();
  Vec2dArray render_absorp();

  Polygon::s_ptr polygon;

  uint32_t layer;
  uint32_t datatype;

  Vec2d pos;
  double rotation;
  double width;
  double height;

  PropertyArray properties;
  Repetition repetition;

  mutable Vec2dArray box;

  QImage m_img;  //QImage

  std::vector<unsigned char> m_img_data;  //图片内容
  std::string m_name;                     //图片名
  int m_order_index = 0;                  //序号
  Vec2dArray m_cell_points = {Vec2d(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()),
                              Vec2d(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()),
                              Vec2d(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN())};  //版图坐标
  Vec2dArray m_img_points = {Vec2d(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()),
                             Vec2d(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()),
                             Vec2d(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN())};  //图片坐标
};

}  // namespace qlib
